/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ui;

import control.MStockMidlet;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
import listener.ICommandListener;
import listener.IKeyListener;

/**
 *
 * @author tho.hoang
 */
public class Grid extends ACanvas {

    protected final int MOVE_LEFT = 3;
    protected final int MOVE_RIGHT = 4;
    private GridItemCollections items = new GridItemCollections();
    // selected
    private AGridItem selectedItem = null;
    private int selectedIndex = -1;
    // layout
    private int maxCols = -1, maxRows = -1, columns = 1;
    private int cols = -1, rows = -1, colSpacing = 0, rowSpacing = 0;
    private int curRow = -1, curCol = -1, maxItemHeight = 0, maxItemWidth = 0;
    private int itemX = 0, itemY = 0, startRow = -1, startCol = -1;
    private boolean isFirstPaint = true, isValid = true;

    public Grid() {
    }

    public Grid(Display display, MStockMidlet control, String title, Image background, Image icon) {
        super(display, control, title, background, icon);
        this.itemX = getItemX();
        this.itemY = getItemY();
        titleAlign = TITLE_CENTER;
    }

    public int getColumns() {
        return columns;
    }

    public void setColumns(int columns) {
        if (columns < 1) {
            throw new IllegalArgumentException("setColumns < 1");
        }
        this.columns = columns;
    }

    public void addItem(AGridItem item) {
        items.addElement(item, this);
    }

    public void removeItem(AGridItem item) {
        items.removeElement(item);
    }

    public AGridItem getItemAt(int index) {
        if (0 <= index && index < items.size()) {
            return items.elementAt(index);
        }
        throw new IllegalArgumentException("setSelectedIndex index=" + index + " | " + items.size());
    }

    public int getItemsSize() {
        return items.size();
    }

    public int getSelectedIndex() {
        return selectedIndex;
    }

    public void setSelectedIndex(int index) {
        if (0 <= index && index < items.size()) {
            this.selectedIndex = index;
            this.selectedItem = items.elementAt(index);
            if (cols != -1) {
                this.curCol = selectedIndex % cols;
                this.curRow = selectedIndex / cols;
                if (curCol < maxCols) {
                    this.startCol = 0;
                } else {
                    this.startCol = curCol - maxCols + 1;
                }
                if (curRow < maxRows) {
                    this.startRow = 0;
                } else {
                    this.startRow = curRow - maxRows + 1;
                }
            }
            return;
        }
        throw new IllegalArgumentException("setSelectedIndex index=" + index + " | " + items.size());
    }

    public AGridItem getSelectedItem() {
        return selectedItem;
    }

    public void setSelectedItem(AGridItem item) {
        if (item == null) {
            throw new IllegalArgumentException("setSelectedItem item=null");
        }

        AGridItem temp = null;
        for (int i = 0; i < items.size(); i++) {
            temp = items.elementAt(i);
            if (temp.getId().equals(item.getId())) {
                this.selectedIndex = i;
                this.selectedItem = temp;
                if (cols != -1) {
                    this.curCol = selectedIndex % cols;
                    this.curRow = selectedIndex / cols;
                    if (curCol < maxCols) {
                        this.startCol = 0;
                    } else {
                        this.startCol = curCol - maxCols + 1;
                    }
                    if (curRow < maxRows) {
                        this.startRow = 0;
                    } else {
                        this.startRow = curRow - maxRows + 1;
                    }
                }
                return;
            }
        }

        throw new IllegalArgumentException("setSelectedItem item is not exists");
    }

    public void paintItems(Graphics g) {
        if (items.size() > 0) {
            if (isFirstPaint) {
                init();
                this.isFirstPaint = false;
            }

            if (isValid) {
                int x = getItemX(), y = itemY + rowSpacing;
                int index = 1;
                AGridItem item = null;
                for (int i = startRow; i < rows; i++) {
                    x = getItemX() + colSpacing;
                    for (int j = startCol; j < cols; j++) {
                        index = i * cols + j;
                        if (index < items.size()) {
                            item = (AGridItem) items.elementAt(index);
                            if (index == selectedIndex) {
                                item.setFocus(true);
                            } else {
                                item.setFocus(false);
                            }
                            item.setMaxWidth(maxItemWidth);
                            item.setMaxHeight(maxItemHeight);
                            item.paint(x, y, g, true);
                            x += maxItemWidth+colSpacing;
                        }
                    }
                    y += maxItemHeight + rowSpacing;
                }
            }
        }
    }

    private void init() {
        int i = 0;
        AGridItem item;

        this.cols = columns;
        this.rows = items.size() / cols;
        if (rows * cols != items.size()) {
            this.rows++;
        }

        for (i = 0; i < items.size(); i++) {
            item = items.elementAt(i);
            if (item.getWidth() > maxItemWidth) {
                this.maxItemWidth = item.getWidth();
            }
            if (item.getHeight() > maxItemHeight) {
                this.maxItemHeight = item.getHeight();
            }
        }

        this.maxCols = getItemWidth() / maxItemWidth;
        this.maxRows = getItemHeight() / maxItemHeight;
        if (maxCols > cols) {
            this.maxCols = cols;
        }
        if (maxRows > rows) {
            this.maxRows = rows;
        }
        if (maxItemWidth * maxCols < getItemWidth()) {
            colSpacing = (getItemWidth() - maxItemWidth * maxCols) / (maxCols + 1);
        }
        if (maxItemHeight * maxRows < getItemHeight()) {
            rowSpacing = (getItemHeight() - maxItemHeight * maxRows) / (maxRows + 1);
        }


        if (selectedIndex == -1 || selectedItem == null) {
            this.selectedIndex = 0;
            this.selectedItem = items.elementAt(0);
            this.curRow = 0;
            this.curCol = 0;
            this.startCol = 0;
            this.startRow = 0;
        } else {
            this.curCol = selectedIndex % cols;
            this.curRow = selectedIndex / cols;
            if (curCol < maxCols) {
                this.startCol = 0;
            } else {
                this.startCol = curCol - maxCols;
            }
            if (curRow < maxRows) {
                this.startRow = 0;
            } else {
                this.startRow = curRow - maxRows;
            }
        }
    }

    public void keyPressed(int key) {
        ICommandListener commandListener = getCommandListener();

        if (key == getLeftSoftKey()) {
            if (commandListener != null && getSelectCommand() != null) {
                commandListener.commandAction(getSelectCommand());
            }

        } else if (key == getRightSoftKey()) {
            if (commandListener != null && getCancelCommand() != null) {
                commandListener.commandAction(getCancelCommand());
            }
        } else {
            IKeyListener keyListener = getKeyListener();
            switch (key) {
                case KEY_NUM0:
                case KEY_NUM1:
                case KEY_NUM2:
                case KEY_NUM3:
                case KEY_NUM4:
                case KEY_NUM5:
                case KEY_NUM6:
                case KEY_NUM7:
                case KEY_NUM8:
                case KEY_NUM9:
                case KEY_STAR:
                case KEY_POUND:
                case FIRE:
                    if (keyListener != null) {
                        keyListener.keyAction(key);
                    }
                    break;
                default:
                    int gameAction = getGameAction(key);
                    if (gameAction == RIGHT) {
                        this.selectedIndex++;
                        if (selectedIndex > items.size() - 1) {
                            this.selectedIndex = 0;
                            this.curRow = 0;
                            this.curCol = 0;
                            this.startCol = 0;
                            this.startRow = 0;

                        } else {
                            if (curCol + 1 < cols) {
                                this.curCol++;
                                if (curCol >= startCol + maxCols) {
                                    this.startCol++;
                                }

                            } else {
                                this.curCol = 0;
                                this.startCol = 0;
                                this.curRow++;
                                if (curRow >= startRow + maxRows) {
                                    this.startRow++;
                                }
                            }
                        }

                    } else if (gameAction == LEFT) {
                        this.selectedIndex--;
                        if (selectedIndex < 0) {
                            this.selectedIndex = items.size() - 1;
                            this.startCol = cols - maxCols;
                            this.startRow = rows - maxRows;
                            if (selectedIndex % cols > startCol + maxCols - 1) {
                                this.startCol = selectedIndex % cols;
                            }
                            this.curCol = selectedIndex % cols;
                            this.curRow = rows - 1;

                        } else {
                            if (curCol - 1 >= 0) {
                                this.curCol--;
                                if (curCol < startCol) {
                                    this.startCol--;
                                }

                            } else {
                                this.curCol = cols - 1;
                                this.startCol = cols - maxCols;
                                this.curRow--;
                                if (curRow < startRow) {
                                    this.startRow--;
                                }
                            }
                        }

                    } else if (gameAction == DOWN) {
                        this.selectedIndex += cols;
                        if (selectedIndex > items.size() - 1) {
                            this.selectedIndex %= cols;
                            this.curRow = 0;
                            this.startRow = 0;

                        } else {
                            this.curRow++;
                            if (curRow >= startRow + maxRows) {
                                this.startRow++;
                            }
                        }
                    } else if (gameAction == UP) {
                        if (selectedIndex - cols < 0) {
                            this.selectedIndex += cols * (rows - 1);
                            this.startRow = rows - maxRows;
                            this.curRow = rows - 1;
                            if (selectedIndex > items.size() - 1) {
                                this.selectedIndex -= cols;
                                this.startRow--;
                                this.curRow--;
                            }

                        } else {
                            this.selectedIndex -= cols;
                            this.curRow--;
                            if (curRow < startRow) {
                                this.startRow--;
                            }
                        }
                    }

                    this.selectedItem = items.elementAt(selectedIndex);
                    this.moveAction = MOVE_LEFT;
                    if (isAutoRepaint()) {
                        repaint();
                    }
                    if (keyListener != null) {
                        keyListener.keyAction(gameAction);
                    }
                    break;
            }
        }
    }
}
